之前在service worker中寫了這麼多cache strategies
、background sync
等等的程式碼,但是隨著我們開發的專案越來越大、檔案越來越多,管理service worker的工作也就越來越複雜。難道沒有什麼方便的工具能讓我們「自動化管理service worker」嗎?
有der~~那就是Google提供的 workbox tool
由於大多數網站都包含html、css、javascript和圖像,這裡我們可以透過Workbox來使用「一些通用策略」對網頁資源進行暫存。
那要怎麼使用workbox呢?首先,先來安裝它的command line套件吧(使用2.0.0版本):
npm install --save-dev workbox-cli@^2.0.0
另外,在package.json中添加npm執行workbox的腳本:
"scripts": {
"start": "http-server -c-1",
"generate-sw": "workbox generate:sw"
}
接著在command line中執行npm run generate-sw
。
畫面會出現一連串的要求設定:
workbox會在專案目錄下產生4個file:
+-- public
| +-- service-worker.js
| +-- workbox-sw.prod.v2.1.3.js
| +-- workbox-sw.prod.v2.1.3.js.map
+-- workbox-cli-config.js
其中在service-worker.js可以發現「fileManifest陣列」中已經設置了非常多準備要cache的檔案,每個file會有一個revisoion,可以把它想成是更新版本號。當這些檔案更新時,再次執行npm run generate-sw
,版本號也會隨之更新:
fileManifest = [
{
"url": "404.html",
"revision": "0a27a4163254fc8fce870c8cc3a3f94f"
},
{
"url": "favicon.ico",
"revision": "2cab47d9e04d664d93c8d91aec59e812"
},
{
"url": "index.html",
"revision": "9aaca300f5d996d0d8f4dbbbc8d2f72c"
},
{
"url": "manifest.json",
"revision": "1fa5aa1aade821474e2063a7521870f2"
},
{
"url": "offline.html",
"revision": "6bca1d9bf0f30b72fcac1826ca248b2b"
},
... 以下省略 ...
]
const workboxSW = new self.WorkboxSW();
workboxSW.precache(fileManifest);
最後兩行為建立一個workbox service worker實例,並透過precache
方法,將上述要暫存的檔案傳入。
在看新的service worker是否能正常運行前,記得在app.js中將註冊service worker從「sw.js」改成「service-worker.js」。
可以發現Cache Storage中已經新增了一個「workbox-precaching」的sub cache:
如果是在離線狀態下呢?
Nooooo!! 雖然已經precache一些靜態檔案了,不過像是material design CDN或是google fonts的圖示都沒有被暫存到。
所以接下來就要來看看要怎麼針對這些「特定的外部url資源」採取「特定的cache strategies」(這些其實在我們舊的sw.js中都已經實作出來了)。
在處理上述的問題前,我在這裡並不想要precacahe icons
以及help
folder。所以必須對workbox-cli-config.js中的「globPatterns」和「globIgnores」屬性進行修改,前者是去定義我們要precache的檔案路徑和類型,後者為要省略的檔案。
"globPatterns": [
"**/*.{html,ico,json,css,js}",
"src/images/*.{jpg,png}" // 這裡我只想要precache src/images路徑下的圖像並不包含icons資料夾
]
"globIgnores": [
"../workbox-cli-config.js",
"help/**" // 將help資料夾下所有的file省略,不進行暫存
]
記得要重新執行
npm run generate-sw
接續剛剛要處理的問題,針對「特定的外部url資源」採取「特定的cache strategies」要怎麼透過workbox來實作呢?這裡就要開始使用workbox中的routing功能。
首先,我現在每次執行npm run generate-sw
指令時,都會重新產生並覆蓋原有的service-worker.js檔案,這樣其實非常沒有效率。
這裡有一個更好的方式,我們只希望更新「要precache的fileManifest陣列」。所以在這邊我新增一個sw-base.js檔案,並在裡面添加:
importScripts('workbox-sw.prod.v2.1.3.js');
const workboxSW = new self.WorkboxSW();
workboxSW.precache([]); // 我用一個空陣列來取代原有的fileManifest陣列
然後在workbox-cli-config.js中將sw-base.js添加到「swSrc
」這個屬性中:
"swSrc": "public/sw-base.js"
接著在package.json中,將原本執行的workbox腳本從「workbox generate:sw
」更改為「workbox inject:manifest
」。
而這個inject:manifest
指令就是讓我們每次執行時,不用再產生全新的service-worker.js file,而是先到config file中的swSrc屬性了解到要以sw-base.js為基礎,並將「更新後的fileManifest陣列」注入到空陣列中,最後把整個結果寫入到service-worker.js檔案中。
接下來終於要在service-worker.js中,加入我們的routing邏輯了(這裡是要針對外部的google fonts CDN):
workboxSW.router.registerRoute(/.*(?:googleapis|gstatic)\.com.*$/, workboxSW.strategies.staleWhileRevalidate({
cacheName: 'google-fonts'
}));
感覺只有短短的幾行,其實workbox幫我們做了非常多的工作。首先,router.registerRoute()
這個方法接受2個參數,第一個為我們要routing的url(可以用正規表達式),第二個為我們要使用的cache strategies。
所以這裡在第一個參數中我將要路由的網址設定為包含了googleapis.com
或gstatic.com
。第二個參數透過strategies這個屬性將所要的cache strategies指定為「staleWhileRevalidate()
」。
staleWhileRevalidate
其實就是之前實作過的「cache then network strategies」,這裡就不多說明XD
而在staleWhileRevalidate()這個method中可以輸入一個javascript object,裡面可以設定的屬性非常多,這裡我只將上述的google fonts外部資源暫存到「google-fonts」這個sub cache中。
Day28 結束!!